package com.xxxy.log;

import com.alibaba.fastjson.JSON;
import com.xxxy.dao.OperationLogDao;
import com.xxxy.model.OperationLog;
import com.xxxy.util.JwtUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

/**
 * @author sjh
 * @date 2022/2/5 20:52
 */
@Aspect
@Component
public class LogAspect{

    private final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    OperationLogDao operationLogDao;

    @Pointcut("@annotation(com.xxxy.log.Log)")
    public void logPointCut(){}

    @AfterReturning(returning = "o", pointcut = "logPointCut()")
    public void doAfter(JoinPoint joinPoint, Object o) throws Exception {

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        OperationLog operationLog = new OperationLog();
        if(request.getHeader("Authorization") != null){
            //操作账号
            operationLog.setUserAccount(jwtUtils.getUserIdFromToken(request.getHeader("Authorization")));
            //操作身份
            operationLog.setUserType(jwtUtils.getUserTypeFromToken(request.getHeader("Authorization")));
        }

        String methodName = joinPoint.getSignature().getName();
        Method method = currentMethod(joinPoint,methodName);
        Log log = method.getAnnotation(Log.class);
        String module = log.module();
        //功能模块
        operationLog.setModule(module);
        String description = log.description();
        //功能描述
        operationLog.setDescription(description);
        //ip地址
        operationLog.setIp(request.getRemoteAddr() + ":" + request.getServerPort());
        //路径地址
        operationLog.setUrl(request.getRequestURI());

        //请求参数
        StringBuilder requestLog = new StringBuilder();
        Signature signature = joinPoint.getSignature();
        String[] paramNames = ((MethodSignature) signature).getParameterNames();
        Object[] paramValues = joinPoint.getArgs();

        int paramLength = null == paramNames ? 0 : paramNames.length;
        if (paramLength == 0) {
            requestLog.append("{}");
        } else {
            requestLog.append("[");
            for (int i = 0; i < paramLength - 1; i++) {
                requestLog.append(paramNames[i]).append("=").append(JSON.toJSONString(paramValues[i])).append(",");
            }
            requestLog.append(paramNames[paramLength - 1]).append("=").append(JSON.toJSONString(paramValues[paramLength - 1])).append("]");
        }
        //请求参数
        operationLog.setParams(requestLog.toString());
        //是否成功(0=不成功,1=成功)
        if(Objects.equals(JSON.parseObject(JSON.toJSONString(o)).getString("code"), "200")){

            if(request.getHeader("Authorization") == null){
                String userAccount = paramValues[0].toString();
                //操作账号
                operationLog.setUserAccount(userAccount);
                //操作身份
                if(userAccount.length() == 10){
                    operationLog.setUserType(1);
                }
                else if(userAccount.length() == 6){
                    operationLog.setUserType(2);
                }
                else {
                    operationLog.setUserType(3);
                }
            }

            operationLog.setSuccess(1);
        } else {
            operationLog.setSuccess(0);
        }
        operationLog.setCreateTime(new Date());
        //保存数据库
        operationLogDao.insert(operationLog);
    }


    /**
     * 获取当前执行的方法
     *
     * @param joinPoint  连接点
     * @param methodName 方法名称
     * @return 方法
     */
    private Method currentMethod(JoinPoint joinPoint, String methodName) {
        /**
         * 获取目标类的所有方法，找到当前要执行的方法
         */
        Method[] methods = joinPoint.getTarget().getClass().getMethods();
        Method resultMethod = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                resultMethod = method;
                break;
            }
        }
        return resultMethod;
    }
}
